#ifndef __CORESIGHT_PRIV_H
#define __CORESIGHT_PRIV_H

#include <linux/types.h>
#include <asm/page-def.h>
#include <asm/local.h>

#if (TRBE_MEM_PERCPU_SIZE & (PAGE_SIZE - 1))
#error "TRBE_MEM_PERCPU_SIZE is not aligned with PAGE_SIZE"
#endif

#if (TRBE_MEM_BASE & (PAGE_SIZE - 1))
#error "TRBE_MEM_BASE is not aligned with PAGE_SIZE"
#endif

#define CORESIGHT_START BIT(0)
#define CORESIGHT_RESUME BIT(1)
#define CORESIGHT_STOP BIT(2)
#define CORESIGHT_SUSPEND BIT(3)

#define CORESIGHT_REG(x) (*((volatile u64 *)(&x)))
#define TRBE_REG_SHOW(m, x) seq_printf(m, #x " = 0x%llx\n", read_sysreg_s(x))
#if DEBUG
#define TRBE_REG_KERNEL_SHOW(x) pr_err(#x " = 0x%llx\n", read_sysreg_s(x))
#else
#define TRBE_REG_KERNEL_SHOW(x)
#endif

typedef struct {
	u64 idle : 1;
	u64 pmstable : 1;
	u64 res0 : 62;
} RegTRCSTATR;

typedef struct {
	u64 enable : 1;
	u64 res0 : 63;
} RegTRCPRGCTLR;

typedef struct {
	u64 res3 : 3;
	u64 bb : 1;
	u64 cci : 1;
	u64 res2 : 1;
	u64 cid : 1;
	u64 vmid : 1;
	u64 res1 : 3;
	u64 ts : 1;
	u64 rs : 1;
	u64 qe : 2;
	u64 vmidopt : 1;
	u64 res0 : 48;
} RegTRCCONFIGR;

typedef struct {
	u64 period : 5;
	u64 res0 : 59;
} RegTRCSYNCPR;

typedef struct {
	u64 traceid : 7;
	u64 res0 : 57;
} RegTRCTRACEIDR;

typedef struct {
	u64 event_sel : 5;
	u64 res4 : 2;
	u64 event_type : 1;
	u64 res3 : 1;
	u64 ssstatus : 1;
	u64 trcreset : 1;
	u64 trcerr : 1;
	u64 res2 : 4;
	u64 exlevel_s_el0 : 1;
	u64 exlevel_s_el1 : 1;
	u64 exlevel_s_el2 : 1;
	u64 exlevel_s_el3 : 1;
	u64 exlevel_ns_el0 : 1;
	u64 exlevel_ns_el1 : 1;
	u64 exlevel_ns_el2 : 1;
	u64 res1 : 1;
	u64 exlevel_rl_el0 : 1;
	u64 exlevel_rl_el1 : 1;
	u64 exlevel_rl_el2 : 1;
	u64 res0 : 37;
} RegTRCVICTLR;

typedef struct {
	u64 threshold : 12;
	u64 res0 : 52;
} RegTRCCCCTLR;

typedef struct {
	u64 event0_sel : 5;
	u64 res4 : 2;
	u64 event0_type : 1;
	u64 event1_sel : 5;
	u64 res3 : 2;
	u64 event1_type : 1;
	u64 event2_sel : 5;
	u64 res2 : 2;
	u64 event2_type : 1;
	u64 event3_sel : 5;
	u64 res1 : 2;
	u64 event3_type : 1;
	u64 res0 : 32;
} RegTRCEVENTCTL0R;

typedef struct {
	u64 insten0 : 1;
	u64 insten1 : 1;
	u64 insten2 : 1;
	u64 insten3 : 1;
	u64 res1 : 7;
	u64 atb : 1;
	u64 lpoverride : 1;
	u64 res0 : 51;
} RegTRCEVENTCTL1R;

typedef struct {
	u64 event_sel : 5;
	u64 res1 : 2;
	u64 event_type : 1;
	u64 res0 : 56;
} RegTRCTSCTLR;

typedef struct {
	u64 include0 : 1;
	u64 include1 : 1;
	u64 include2 : 1;
	u64 include3 : 1;
	u64 include4 : 1;
	u64 include5 : 1;
	u64 include6 : 1;
	u64 include7 : 1;
	u64 res1 : 8;
	u64 exclude0 : 1;
	u64 exclude1 : 1;
	u64 exclude2 : 1;
	u64 exclude3 : 1;
	u64 exclude4 : 1;
	u64 exclude5 : 1;
	u64 exclude6 : 1;
	u64 exclude7 : 1;
	u64 res0 : 40;
} RegTRCVIIECTLR;

typedef struct {
	u64 start0 : 1;
	u64 start1 : 1;
	u64 start2 : 1;
	u64 start3 : 1;
	u64 start4 : 1;
	u64 start5 : 1;
	u64 start6 : 1;
	u64 start7 : 1;
	u64 start8 : 1;
	u64 start9 : 1;
	u64 start10 : 1;
	u64 start11 : 1;
	u64 start12 : 1;
	u64 start13 : 1;
	u64 start14 : 1;
	u64 start15 : 1;
	u64 stop0 : 1;
	u64 stop1 : 1;
	u64 stop2 : 1;
	u64 stop3 : 1;
	u64 stop4 : 1;
	u64 stop5 : 1;
	u64 stop6 : 1;
	u64 stop7 : 1;
	u64 stop8 : 1;
	u64 stop9 : 1;
	u64 stop10 : 1;
	u64 stop11 : 1;
	u64 stop12 : 1;
	u64 stop13 : 1;
	u64 stop14 : 1;
	u64 stop15 : 1;
	u64 res0 : 32;
} RegTRCVISSCTLR;

typedef struct {
	u64 range0 : 1;
	u64 range1 : 1;
	u64 range2 : 1;
	u64 range3 : 1;
	u64 range4 : 1;
	u64 range5 : 1;
	u64 range6 : 1;
	u64 range7 : 1;
	u64 mode : 1;
	u64 res0 : 55;
} RegTRCBBCTLR;

typedef struct {
	u64 extin0 : 1;
	u64 extin1 : 1;
	u64 extin2 : 1;
	u64 extin3 : 1;
	u64 res1 : 4;
	u64 event0 : 1;
	u64 event1 : 1;
	u64 event2 : 1;
	u64 event3 : 1;
	u64 ta : 1;
	u64 res0 : 51;
} RegTRCRSR;

typedef struct {
	u64 enable : 1;
	u64 fm : 2;
	u64 tm : 2;
	u64 nvm : 1;
	u64 res0 : 6;
	u64 limit : 52;
} RegTRBLIMITR;

typedef struct {
	u64 ptr;
} RegTRBPTR;

typedef struct {
	u64 res0 : 12;
	u64 base : 52;
} RegTRBBASER;

typedef struct {
	u64 mss : 16;
	u64 res3 : 1;
	u64 s : 1;
	u64 ea : 1;
	u64 res2 : 1;
	u64 wrap : 1;
	u64 trg : 1;
	u64 irq : 1;
	u64 res1 : 3;
	u64 ec : 6;
	u64 res0 : 32;
} RegTRBSR;

typedef struct {
	RegTRCSTATR trcstatr;
	RegTRCPRGCTLR trcprgctlr;
	RegTRCCONFIGR trcconfigr;
	RegTRCSYNCPR trcsyncpr;
	RegTRCTRACEIDR trctraceidr;
	RegTRCVICTLR trcvictlr;
	RegTRCCCCTLR trcccctlr;
	RegTRCEVENTCTL0R trceventctl0r;
	RegTRCEVENTCTL1R trceventctl1r;
	RegTRCTSCTLR trctsctlr;
	RegTRCVIIECTLR trcviiectlr;
	RegTRCVISSCTLR trcvissctlr;
	RegTRCBBCTLR trcbbctlr;
	RegTRCRSR trcrsr;
} EteRegs;

typedef struct {
	RegTRBLIMITR trblimitr;
	RegTRBPTR trbptr;
	RegTRBBASER trbbaser;
	RegTRBSR trbsr;
} TrbeRegs;

typedef struct {
	u32 flag;
	EteRegs ete;
	TrbeRegs trbe;
} CoresightDesc;

void coresight_start(void *arg);
void coresight_stop(void *arg);
int coresight_smp_init(void);
void coresight_smp_exit(void);
void coresight_disable_cpus(const struct cpumask *cpumask);
int coresight_enable_cpus(const struct cpumask *cpumask);

#endif
